﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EnhancedSerialCommunication
{
    public partial class EnhancedSerialPortForm : Form
    {
        private SerialPort _serialPort;
        private delegate void UpdateRichTextBoxDelegate(string text);
        private HttpClient _httpClient;
        private string _serverUrl = "http://960.city/scanpen/receive.php"; // 替换为你的服务器地址
        private int _defaultBaudRate = 1000000; // 默认波特率：一百万
        private bool _isPaused = false; // 暂停接收标志

        public EnhancedSerialPortForm()
        {
            InitializeComponent();
            InitializeControls();
            _httpClient = new HttpClient();
            _httpClient.Timeout = TimeSpan.FromSeconds(10);
        }

        private void InitializeControls()
        {
            // 窗体基本设置
            this.Text = "串口数据管理助手";
            this.Size = new System.Drawing.Size(850, 730);
            this.FormClosing += SerialPortDataManagerForm_FormClosing;

            // 串口选择下拉框
            ComboBox cmbSerialPorts = new ComboBox
            {
                Name = "cmbSerialPorts",
                Location = new System.Drawing.Point(20, 20),
                Width = 150,
                DropDownStyle = ComboBoxStyle.DropDownList
            };
            cmbSerialPorts.SelectedIndexChanged += CmbSerialPorts_SelectedIndexChanged;
            this.Controls.Add(cmbSerialPorts);

            // 波特率输入框及标签
            Label lblBaudRate = new Label
            {
                Name = "lblBaudRate",
                Text = "波特率:",
                Location = new System.Drawing.Point(180, 23),
                Width = 60
            };
            this.Controls.Add(lblBaudRate);

            TextBox txtBaudRate = new TextBox
            {
                Name = "txtBaudRate",
                Text = _defaultBaudRate.ToString(),
                Location = new System.Drawing.Point(240, 20),
                Width = 120
            };
            this.Controls.Add(txtBaudRate);

            // 刷新按钮
            Button btnRefresh = new Button
            {
                Name = "btnRefresh",
                Text = "刷新串口",
                Location = new System.Drawing.Point(370, 20),
                Width = 100
            };
            btnRefresh.Click += (sender, e) => LoadSerialPorts(cmbSerialPorts);
            this.Controls.Add(btnRefresh);

            // 打开/关闭串口按钮
            Button btnTogglePort = new Button
            {
                Name = "btnTogglePort",
                Text = "打开串口",
                Location = new System.Drawing.Point(480, 20),
                Width = 100
            };
            btnTogglePort.Click += BtnTogglePort_Click;
            this.Controls.Add(btnTogglePort);

            // 发送文件按钮
            Button btnSendFile = new Button
            {
                Name = "btnSendFile",
                Text = "发送TXT文件",
                Location = new System.Drawing.Point(590, 20),
                Width = 120,
                Enabled = false // 初始禁用，打开串口后启用
            };
            btnSendFile.Click += BtnSendFile_Click;
            this.Controls.Add(btnSendFile);

            // 服务器地址输入框
            Label lblServerUrl = new Label
            {
                Name = "lblServerUrl",
                Text = "服务器地址:",
                Location = new System.Drawing.Point(20, 55),
                Width = 80
            };
            this.Controls.Add(lblServerUrl);

            TextBox txtServerUrl = new TextBox
            {
                Name = "txtServerUrl",
                Text = _serverUrl,
                Location = new System.Drawing.Point(100, 55),
                Width = 510
            };
            txtServerUrl.TextChanged += (sender, e) =>
                _serverUrl = (sender as TextBox)?.Text ?? _serverUrl;
            this.Controls.Add(txtServerUrl);

            // 数据操作按钮组
            Panel buttonPanel = new Panel
            {
                Name = "buttonPanel",
                Location = new System.Drawing.Point(20, 90),
                Width = 780,
                Height = 30
            };
            this.Controls.Add(buttonPanel);

            // 清空按钮
            Button btnClear = new Button
            {
                Name = "btnClear",
                Text = "清空",
                Location = new System.Drawing.Point(0, 0),
                Width = 80
            };
            btnClear.Click += BtnClear_Click;
            buttonPanel.Controls.Add(btnClear);

            // 暂停按钮
            Button btnPause = new Button
            {
                Name = "btnPause",
                Text = "暂停",
                Location = new System.Drawing.Point(90, 0),
                Width = 80
            };
            btnPause.Click += BtnPause_Click;
            buttonPanel.Controls.Add(btnPause);

            // 保存按钮
            Button btnSave = new Button
            {
                Name = "btnSave",
                Text = "保存",
                Location = new System.Drawing.Point(180, 0),
                Width = 80
            };
            btnSave.Click += BtnSave_Click;
            buttonPanel.Controls.Add(btnSave);

            // 接收区域标签
            Label lblReceivedData = new Label
            {
                Name = "lblReceivedData",
                Text = "接收数据:",
                Location = new System.Drawing.Point(20, 125),
                Width = 100
            };
            this.Controls.Add(lblReceivedData);

            // 接收数据显示框
            RichTextBox rtbReceivedData = new RichTextBox
            {
                Name = "rtbReceivedData",
                Location = new System.Drawing.Point(20, 150),
                Width = 780,
                Height = 480,
                ReadOnly = true,
                ScrollBars = RichTextBoxScrollBars.Vertical,
                Font = new System.Drawing.Font("微软雅黑", 9F)  // 设置支持中文的字体
            };
            this.Controls.Add(rtbReceivedData);

            // 初始加载串口列表
            LoadSerialPorts(cmbSerialPorts);
        }

        #region 串口管理
        private void LoadSerialPorts(ComboBox comboBox)
        {
            try
            {
                string currentSelection = comboBox.SelectedItem?.ToString();
                comboBox.Items.Clear();

                string[] portNames = SerialPort.GetPortNames();

                if (portNames.Length == 0)
                {
                    comboBox.Items.Add("无可用串口");
                    comboBox.SelectedIndex = 0;
                    GetToggleButton().Enabled = false;
                    GetSendFileButton().Enabled = false;
                }
                else
                {
                    comboBox.Items.AddRange(portNames);

                    if (!string.IsNullOrEmpty(currentSelection) && comboBox.Items.Contains(currentSelection))
                    {
                        comboBox.SelectedItem = currentSelection;
                    }
                    else
                    {
                        comboBox.SelectedIndex = 0;
                    }
                    GetToggleButton().Enabled = true;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载串口失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void BtnTogglePort_Click(object sender, EventArgs e)
        {
            Button toggleButton = sender as Button;
            ComboBox portCombo = GetPortComboBox();
            TextBox baudRateTextBox = GetBaudRateTextBox();

            if (_serialPort == null || !_serialPort.IsOpen)
            {
                // 验证波特率输入
                if (!int.TryParse(baudRateTextBox.Text, out int baudRate) || baudRate <= 0)
                {
                    MessageBox.Show($"无效的波特率值: {baudRateTextBox.Text}\r\n请输入有效的正整数", "输入错误",
                                  MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    baudRateTextBox.Focus();
                    return;
                }

                // 打开串口
                if (portCombo.SelectedItem.ToString() == "无可用串口")
                {
                    MessageBox.Show("没有可用的串口可打开", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                try
                {
                    string portName = portCombo.SelectedItem.ToString();

                    _serialPort = new SerialPort(portName)
                    {
                        BaudRate = baudRate,      // 使用用户输入的波特率
                        DataBits = 8,
                        StopBits = StopBits.One,
                        Parity = Parity.None,
                        Handshake = Handshake.None,
                        ReadTimeout = 500,
                        WriteTimeout = 500
                    };

                    _serialPort.DataReceived += SerialPort_DataReceived;
                    _serialPort.Open();

                    if (_serialPort.IsOpen)
                    {
                        toggleButton.Text = "关闭串口";
                        portCombo.Enabled = false;
                        baudRateTextBox.Enabled = false; // 打开后禁用波特率修改
                        GetRefreshButton().Enabled = false;
                        GetSendFileButton().Enabled = true;
                        AppendToRichTextBox($"已成功打开串口: {portName}，波特率: {baudRate}\r\n");

                        // 打开串口时恢复接收状态
                        _isPaused = false;
                        GetPauseButton().Text = "暂停";
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"打开串口失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    _serialPort = null;
                }
            }
            else
            {
                // 关闭串口
                try
                {
                    string portName = _serialPort.PortName;
                    int baudRate = _serialPort.BaudRate;

                    _serialPort.Close();
                    _serialPort.DataReceived -= SerialPort_DataReceived;
                    _serialPort.Dispose();
                    _serialPort = null;

                    toggleButton.Text = "打开串口";
                    portCombo.Enabled = true;
                    GetBaudRateTextBox().Enabled = true; // 关闭后允许修改波特率
                    GetRefreshButton().Enabled = true;
                    GetSendFileButton().Enabled = false;
                    AppendToRichTextBox($"已关闭串口: {portName}，波特率: {baudRate}\r\n");
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"关闭串口失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        #endregion

        #region 数据接收与分析
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // 如果处于暂停状态，不处理接收的数据
            if (_isPaused)
                return;

            try
            {
                if (_serialPort != null && _serialPort.IsOpen)
                {
                    string data = _serialPort.ReadExisting();

                    if (!string.IsNullOrEmpty(data))
                    {
                        string timestampedData = $"[{DateTime.Now:HH:mm:ss.fff}] 收到: {data}\r\n";
                        AppendToRichTextBox(timestampedData);

                        // 分析数据并推送
                        AnalyzeAndPushData(data);
                    }
                }
            }
            catch (Exception ex)
            {
                if (!_isPaused) // 暂停状态下不显示错误
                {
                    AppendToRichTextBox($"接收数据出错: {ex.Message}\r\n");
                }
            }
        }

        private void AnalyzeAndPushData(string data)
        {
            // 这里是数据分析逻辑，根据实际需求修改
            // 示例：如果数据包含"temperature:"，则提取温度值并推送
            if (data.Contains("temperature:"))
            {
                try
                {
                    string temperature = data.Split(new[] { "temperature:" }, StringSplitOptions.None)[1].Trim();
                    if (double.TryParse(temperature, out double tempValue))
                    {
                        // 温度超过阈值才推送（示例）
                        if (tempValue > 30)
                        {
                            var payload = new
                            {
                                type = "temperature",
                                value = tempValue,
                                timestamp = DateTime.Now.ToString("o")
                            };
                            PushDataToServer(payload);
                        }
                    }
                }
                catch (Exception ex)
                {
                    AppendToRichTextBox($"数据分析出错: {ex.Message}\r\n");
                }
            }
            // 可以添加更多分析规则...
        }

        private async void PushDataToServer(object data)
        {
            if (_isPaused) // 暂停状态下不推送数据
                return;

            if (string.IsNullOrEmpty(_serverUrl) || !_serverUrl.StartsWith("http"))
            {
                AppendToRichTextBox("服务器地址无效，无法推送数据\r\n");
                return;
            }

            try
            {
                // 转换数据为JSON
                string jsonData = Newtonsoft.Json.JsonConvert.SerializeObject(data);
                var content = new StringContent(jsonData, Encoding.UTF8, "application/json");

                // 发送POST请求
                var response = await _httpClient.PostAsync(_serverUrl, content);
                response.EnsureSuccessStatusCode();

                string result = await response.Content.ReadAsStringAsync();
                AppendToRichTextBox($"[{DateTime.Now:HH:mm:ss.fff}] 数据推送成功: {result}\r\n");
            }
            catch (Exception ex)
            {
                AppendToRichTextBox($"[{DateTime.Now:HH:mm:ss.fff}] 数据推送失败: {ex.Message}\r\n");
            }
        }
        #endregion

        #region 文件发送功能
        private void BtnSendFile_Click(object sender, EventArgs e)
        {
            if (_serialPort == null || !_serialPort.IsOpen)
            {
                MessageBox.Show("请先打开串口", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Filter = "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*",
                Title = "选择要发送的TXT文件"
            };

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                // 在后台线程处理文件发送，避免UI卡顿
                Task.Run(() => SendFileContent(openFileDialog.FileName));
            }
        }

        private void SendFileContent(string filePath)
        {
            try
            {
                if (!File.Exists(filePath))
                {
                    AppendToRichTextBox($"文件不存在: {filePath}\r\n");
                    return;
                }

                // 读取文件所有行
                string[] lines = File.ReadAllLines(filePath);
                AppendToRichTextBox($"开始发送文件: {Path.GetFileName(filePath)}，共 {lines.Length} 行\r\n");

                // 逐行发送
                foreach (string line in lines)
                {
                    if (_serialPort == null || !_serialPort.IsOpen)
                    {
                        AppendToRichTextBox("串口已关闭，停止发送文件\r\n");
                        return;
                    }

                    try
                    {
                        // 发送一行数据
                        _serialPort.WriteLine(line);
                        AppendToRichTextBox($"[{DateTime.Now:HH:mm:ss.fff}] 发送: {line}\r\n");

                        // 每行间隔100毫秒
                        Thread.Sleep(100);
                    }
                    catch (Exception ex)
                    {
                        AppendToRichTextBox($"发送失败: {ex.Message}\r\n");
                        break;
                    }
                }

                AppendToRichTextBox($"文件发送完成: {Path.GetFileName(filePath)}\r\n");
            }
            catch (Exception ex)
            {
                AppendToRichTextBox($"处理文件时出错: {ex.Message}\r\n");
            }
        }
        #endregion

        #region 新增数据操作功能
        // 清空按钮点击事件
        private void BtnClear_Click(object sender, EventArgs e)
        {
            RichTextBox rtb = GetRichTextBox();
            if (rtb.InvokeRequired)
            {
                rtb.Invoke(new Action(() => rtb.Clear()));
            }
            else
            {
                rtb.Clear();
            }
            AppendToRichTextBox("数据已清空\r\n");
        }

        // 暂停/恢复按钮点击事件
        private void BtnPause_Click(object sender, EventArgs e)
        {
            Button pauseButton = sender as Button;
            _isPaused = !_isPaused;

            if (_isPaused)
            {
                pauseButton.Text = "恢复";
                AppendToRichTextBox("已暂停接收数据\r\n");
            }
            else
            {
                pauseButton.Text = "暂停";
                AppendToRichTextBox("已恢复接收数据\r\n");
            }
        }

        // 保存按钮点击事件
        private void BtnSave_Click(object sender, EventArgs e)
        {
            RichTextBox rtb = GetRichTextBox();
            if (string.IsNullOrEmpty(rtb.Text))
            {
                MessageBox.Show("没有可保存的数据", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            // 生成默认文件名：当前时间（格式化为文件名安全格式）
            string defaultFileName = DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".txt";

            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Filter = "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*",
                DefaultExt = "txt",
                FileName = defaultFileName,
                Title = "保存接收的数据"
            };

            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    // 保存RichTextBox中的内容到文件
                    File.WriteAllText(saveFileDialog.FileName, rtb.Text);
                    AppendToRichTextBox($"数据已保存到: {saveFileDialog.FileName}\r\n");
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"保存文件失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
        #endregion

        #region UI辅助方法
        private void AppendToRichTextBox(string text)
        {
            // 如果处于暂停状态，不添加文本到显示框
            if (_isPaused)
                return;

            RichTextBox rtb = GetRichTextBox();

            if (rtb.InvokeRequired)
            {
                UpdateRichTextBoxDelegate del = new UpdateRichTextBoxDelegate(AppendToRichTextBox);
                rtb.Invoke(del, new object[] { text });
            }
            else
            {
                rtb.AppendText(text);
                rtb.ScrollToCaret();
            }
        }

        private void CmbSerialPorts_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;
            if (comboBox != null && comboBox.SelectedItem != null)
            {
                string selectedPort = comboBox.SelectedItem.ToString();
                if (selectedPort != "无可用串口" && (_serialPort == null || !_serialPort.IsOpen))
                {
                    GetToggleButton().Enabled = true;
                }
            }
        }

        private void SerialPortDataManagerForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_serialPort != null && _serialPort.IsOpen)
            {
                _serialPort.Close();
                _serialPort.Dispose();
            }
            _httpClient?.Dispose();
        }

        // 控件获取辅助方法
        private ComboBox GetPortComboBox() => this.Controls["cmbSerialPorts"] as ComboBox;
        private TextBox GetBaudRateTextBox() => this.Controls["txtBaudRate"] as TextBox;
        private Button GetRefreshButton() => this.Controls["btnRefresh"] as Button;
        private Button GetToggleButton() => this.Controls["btnTogglePort"] as Button;
        private Button GetSendFileButton() => this.Controls["btnSendFile"] as Button;
        private RichTextBox GetRichTextBox() => this.Controls["rtbReceivedData"] as RichTextBox;
        private Button GetPauseButton() => (this.Controls["buttonPanel"] as Panel)?.Controls["btnPause"] as Button;
        #endregion

    }
}
